#include "views/linkview.h"
#include "ui_linkview.h"

LinkView::LinkView(QWidget *parent) :
	AbstractView(parent),
    ui(new Ui::LinkView)
{
    ui->setupUi(this);
    renderer = vtkRenderer::New();
	renderer->SetBackground(0.93,0.93,0.93);

    ui->qvtkWidget->GetRenderWindow()->AddRenderer(renderer);

}

LinkView::~LinkView()
{
    delete ui;
}

void LinkView::setInteractorStyle(View3DInteractorStyle *st)
{
	ui->qvtkWidget->GetRenderWindow()->GetInteractor()->SetInteractorStyle(st);
	st->setRenderer(renderer);

	connect(st,SIGNAL(selectedRegionsChanged(const QVector<int>&,AbstractView::SelectAction)),this, SLOT(on_selectionChanged(const QVector<int>&,AbstractView::SelectAction)));
	connect(st,SIGNAL(selectedLinksChanged(const QVector<QPoint>&,AbstractView::SelectAction)),this, SLOT(on_selectionChanged(const QVector<QPoint>&,AbstractView::SelectAction)));
	connect(st,SIGNAL(objectInfoRequested(const QPoint&,int,int)),this,SLOT(on_objectInfoRequested(const QPoint&,int,int)));
}

void LinkView::setNetwork(FunctionalNetwork *net)
{
	AbstractView::setNetwork(net);
	connect(net,SIGNAL(viewUpdateRequired()),this,SLOT(on_viewUpdateRequired()));
	network->attachToRenderer(renderer);
	renderer->ResetCamera();
}

void LinkView::updateView()
{
	int finger = 0;
	//#pragma omp parallel for num_threads(4)
	for(int i = 0;i<network->getRegions().size();i++)
	{
		network->getTemplate()->getRegion(i)->setLinkNodeVisible(false);
		network->getTemplate()->getRegion(i)->setLinkNodeVisible(false);
	}

	//#pragma omp parallel for num_threads(4)
	for(int i = 0;i<network->getCurrentIndividualMatrix()->height();i++)
	{
		for(int j = i+1;j<network->getCurrentIndividualMatrix()->width();j++)
		{
			network->getLinks().at(finger)->setCorrelation(network->getCurrentIndividualMatrix()->at(i,j));
	        network->getLinks().at(finger)->setVisible(false);
			finger++;
		}
	}

	//#pragma omp parallel for num_threads(4)
    for(int i = 0;i<network->getSelection().size();i++)
		network->getSelection().at(i)->setVisible(network->getSelection().at(i)->isEnabled());

	//#pragma omp parallel for num_threads(4)
	for(int i = 0;i<network->getSelection().size();i++)
	{
		network->getSelection().at(i)->regionA()->setLinkNodeVisible(true);
		network->getSelection().at(i)->regionB()->setLinkNodeVisible(true);
	}

	renderer->GetRenderWindow()->Render();
}

void LinkView::on_selectionChanged(const QVector<int> &regions, SelectAction action)
{
	SelectedRegions newSelection;

	QVector<AnatomicalRegion*> allregions = network->getRegions();

	for(int i = 0; i < allregions.size(); i++)
	{
		if(regions.contains(allregions.at(i)->info().RegionID))
			newSelection.push_back(allregions.at(i));
	}
	setSelection(newSelection);
}


void LinkView::on_selectionChanged(const QVector<QPoint> &links, SelectAction action)
{
	SelectedLinks newSelection;

	QVector<AnatomicalLink*> allLinks = network->getLinks();

	switch(action)
	{
	case RemoveFromSelection:
		{
			//loop through current selection and only copy those that are not in 'links' to the new selection
			for(int i = 0;i < network->getSelection().size();i++)
			{
				AnatomicalLink* current = network->getSelection().at(i);
				if(!links.contains(QPoint(current->regionA()->info().RegionID, current->regionB()->info().RegionID)) && 
					!links.contains(QPoint(current->regionB()->info().RegionID, current->regionA()->info().RegionID)))
					newSelection.push_back(current);
			}
		};break;
	case AddToSelection:
		{
			//append the old ones
			for(int i = 0;i < network->getSelection().size();i++)
			{
				if(newSelection.indexOf(network->getSelection().at(i))<0)
					newSelection.push_back(network->getSelection().at(i));
			}
		};//do not break
	case NewSelection:
		{
			//add the new selected links
			for(int i = 0;i<allLinks.size();i++)
			{
				if(links.contains(QPoint(allLinks.at(i)->regionA()->info().RegionID, allLinks.at(i)->regionB()->info().RegionID)) || 
					links.contains(QPoint(allLinks.at(i)->regionB()->info().RegionID, allLinks.at(i)->regionA()->info().RegionID)))
						newSelection.push_back(allLinks.at(i));
			}
		};break;
	}

	setSelection(newSelection);
}

void LinkView::on_matrixChanged()
{
	QVector<AnatomicalRegion*> allregions = network->getRegions();
	QVector<AnatomicalLink*> allLinks = network->getLinks();
	
	double max = 0;
	double min = -1;

	//#pragma omp parallel for num_threads(4)
	for(int i = 0; i<allregions.size(); i++){
		double currentCor = 0;
		for(int j = 0;j<allLinks.size();j++)
		{
			if(allLinks.at(j)->regionA()->info().RegionID == allregions.at(i)->info().RegionID ||
				 allLinks.at(j)->regionB()->info().RegionID == allregions.at(i)->info().RegionID)
			{
				currentCor += abs(allLinks.at(j)->correlation()); 
			}
		}
		if( currentCor > max )
			max = currentCor;
		else if( currentCor < min || min==-1)
			min = currentCor;
	}
	
	//#pragma omp parallel for num_threads(4)
	for(int i = 0; i<allregions.size(); i++){
		double absCor = 0;
		
		for(int j = 0;j<allLinks.size();j++)
		{
			if(allLinks.at(j)->regionA()->info().RegionID == allregions.at(i)->info().RegionID ||
				 allLinks.at(j)->regionB()->info().RegionID == allregions.at(i)->info().RegionID)
					absCor += abs(allLinks.at(j)->correlation()); 
		}
		AnatomicalRegion *region = network->getTemplate()->getRegionById(allregions.at(i)->info().RegionID);
		region->setSphereRadius(absCor, min, max);
		
	}
	
	AbstractView::on_matrixChanged();
	
}

void LinkView::on_objectInfoRequested(const QPoint& point, int regId1, int regId2)
{
	AnatomicalRegion* reg = network->getRegionById(regId1);
	if(regId1 == regId2)
	{
		AnatomicalRegion *reg = network->getRegionById(regId1);
		QString infoString1 = tr("Region %1 (%2)").arg(regId1).arg(reg->info().ShortName.c_str());
		QString infoString2 = tr("%1").arg(reg->info().LongName.c_str());
/*#ifdef _DEBUG
		QMenu menu("",this);
		menu.addAction(infoString1);
		menu.addAction(infoString2);
		menu.exec(QCursor::pos());
#else*/
		QToolTip::showText(QCursor::pos(),infoString1+tr("<br>")+infoString2,this);
//#endif
	}
	else
	{
		AnatomicalRegion* reg2 = network->getRegionById(regId2);
		AnatomicalLink* link = network->getLinkByRegionIds(regId1,regId2);
/*#ifdef _DEBUG
		QMenu menu(tr("Link between region %1 and %2").arg(regId1).arg(regId2),this);
		menu.addAction(tr("Link between region %1 and %2").arg(regId1).arg(regId2));
		menu.addSeparator();
		menu.addAction(tr("Region %1: %2").arg(regId1).arg(QString::fromStdString(reg->info().LongName)));
		menu.addAction(tr("Region %1: %2").arg(regId2).arg(QString::fromStdString(reg2->info().LongName)));
		menu.addSeparator();
		menu.addAction(tr("Correlation: %1").arg(link->correlation()));
		menu.addAction(tr("Anatomical distance: %1cm").arg(link->distance()));
		menu.addSeparator();
		menu.exec(QCursor::pos());
#else*/
		QString text = tr("Link between region %1 and %2").arg(regId1).arg(regId2); 
		text+="<hr>";
		text+=tr("Region %1: %2<br>").arg(regId1).arg(reg->info().LongName.c_str());
		text+=tr("Region %1: %2").arg(regId2).arg(reg2->info().LongName.c_str());
		text+="<hr>";
		text+=tr("Correlation: %1<br>").arg(link->correlation());
		text+=tr("Anatomical distance: %1cm").arg(link->distance());
		text+="<hr>";

		QToolTip::showText(QCursor::pos(),text,this);
//#endif
	}

}